/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_bfile_accessor.c                               */
/*  NOTE      =                                                    */
/*  DATE      = 2015/01/14 by songbb                               */
/*******************************************************************/

#include "frcomm.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../ora_mar_engine.h"
#include "ora_bfile_accessor.h"
#include "../../comm/ora_util.h"
#include "../ora_ttc_proto.h"

/*
FR_STATIC int __ora_bfile_is_prefetched(int i_lob_prefetch_size_for_this_column
                                        , Sql_metadata_info *p_st_metadata)
{
    return (p_st_metadata->i_ora_dml_returned_param == FR_NO && i_lob_prefetch_size_for_this_column > -1) ? FR_YES : FR_NO;
}
*/

/*******************************************************************************
*  FUNC     :  解析 bfile 类型数据
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_metadata                       (meta信息)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_bfile_accessor_unmarshal_one_row(Conntrack *p_st_conn
                                        , L7session_ora *p_st_sess
                                        , long long ll_options
                                        , L7_ora_packet *p_st_ora_packet
                                        , Sql_metadata_info *p_st_metadata)
{
    long long ll_tmp = 0LL;
    long long ll_datalen = 0LL;
    int i_lob_prefetch_size_for_this_column = 0;
    short s_tmp = 0;
    int i_ret = 0;
    int i_isPrefetched;

    if (p_st_metadata->i_isuseless == FR_YES || p_st_metadata->i_isnullbydescribe == FR_YES)
        goto success;

    /**
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/jdbc_oci8/11.2.0.1z/11.2.0.2.0_11.2.0.1_jdbc_oci8_gb2312_all.pcap
     * UP
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [314]
     * tns version? [314]
     * ttc version? [6]
     * version number? [11201]
     * oracle version? [8100]
     * i_ptr_len? [8]
     *
     * ./apm -n -t1 -d /mnt/hgfs/intellij14/apm/global/pcap/data_dev/oracle/sqlplus_oci_oracle/10.2.0.4.0_z_gb2312/sqlplus_gb2312_192.168.18.233_10.2.0.4.0_z_2_192.168.18.168_11.2.0.2_a.pcap
     * DOWN
     * is use oci? [true]
     * is use special field? [true]
     * tns version send? [313]
     * tns version? [313]
     * ttc version? [4]
     * version number? [11202]
     * oracle version? [8100]
     * i_ptr_len? [8]
     */

    if ((p_st_sess->i_use_oci == FR_YES &&
         ((p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_8 && p_st_sess->s_tns_version >= 314)
          || p_st_sess->i_ptr_len == APM_ORA_PTR_LEN_1)) || p_st_sess->i_use_oci == FR_NO
            )
    {
        ORA_PRINT_INFO("bfile_accessor up\n");
        if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_datalen) != FR_SUCC)
            goto error;

        if (ll_datalen == 0LL)
            goto success;

        if (ora_mar_peekUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
            goto error;
        if (ora_mar_escapeSequenceNull(s_tmp, &i_ret) != FR_SUCC)
            goto error;
        if ((i_ret != 1 && s_tmp == 0xfe) || (ll_datalen == s_tmp))
            i_isPrefetched = FR_NO;
        else
            i_isPrefetched = FR_YES;

        ORA_PRINT_DBG("set BFILE i_isPrefetched = %s\n", i_isPrefetched == FR_YES ? "FR_YES" : "FR_NO");

        if (i_isPrefetched == FR_YES)
        {
            if (ora_mar_unmarshalSB8(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // prefetchedLength
                goto error;
            if (p_st_sess->i_useLobPrefetch == APM_ORA_FLAG_UNSET)
            {
                if (ora_mar_peekUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                    goto error;
                if (s_tmp == 0x00)
                {
                    if (ora_get_jdbc_type(p_st_metadata->i_data_type) == ORA_JDBCTYPE_BFILE && p_st_metadata->i_ora_oacmxl > 0)
                        p_st_sess->i_useLobPrefetch = FR_YES;
                    if (ora_mar_skipUB1(p_st_ora_packet) != FR_SUCC)
                        goto error;
                }
                else if (s_tmp == 0xfe || ll_datalen == s_tmp)
                {
                    if (ora_get_jdbc_type(p_st_metadata->i_data_type) == ORA_JDBCTYPE_BFILE && p_st_metadata->i_ora_oacmxl > 0)
                        p_st_sess->i_useLobPrefetch = FR_NO;
                }
                else // XXX: 假设存在UB1
                {
                    if (ora_mar_skipUB1(p_st_ora_packet) != FR_SUCC)
                        goto error;
                }

                ORA_PRINT_DBG("set i_useLobPrefetch = %s\n", p_st_sess->i_useLobPrefetch == APM_ORA_FLAG_UNSET ? "UNSET" : (p_st_sess->i_useLobPrefetch == FR_YES ? "FR_YES" : "FR_NO"));
            }
            else
            {
                if (p_st_sess->i_useLobPrefetch == FR_YES && ora_get_jdbc_type(p_st_metadata->i_data_type) ==
                                                             ORA_JDBCTYPE_BFILE)
                    i_lob_prefetch_size_for_this_column = p_st_metadata->i_ora_oacmxl;
                else
                    i_lob_prefetch_size_for_this_column = -1;
                if (i_lob_prefetch_size_for_this_column > 0)
                {
                    if (ora_mar_skipUB1(p_st_ora_packet) != FR_SUCC)
                        goto error;
                }
            }
        }

        if (ora_mar_skipCLR(p_st_sess, p_st_ora_packet) != FR_SUCC)
            goto error;
    }
    else
    {
        ORA_PRINT_INFO("bfile_accessor down\n");
        if (ora_mar_skipDALC(p_st_sess, p_st_ora_packet) != FR_SUCC)
            goto error;
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}
